%{
/*********************************************
YACC file
基础程序
Date:2023/9/19
forked SherryXiye
**********************************************/
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#ifndef YYSTYPE
#define YYSTYPE double
#endif
int yylex();
extern int yyparse();
FILE* yyin;
void yyerror(const char* s);
%}
//注意先后定义的优先级区别
%token '+' '-'
%token NUMBER
%token '*' '/'
%token '(' ')'
%left '+' '-'
%left '*' '/'
%left '(' ')' 
%right UMINUS         

%%


lines   :       lines expr ';' { printf("%f\n", $2); }
        |       lines ';'
        |
        ;

expr    :       expr '+' expr   { $$=$1+$3; }
        |       expr '-' expr   { $$=$1-$3; }
        |       expr '*' expr   { $$=$1*$3; }
        |       expr '/' expr   { $$=$1/$3; }
        |       '('expr')'      { $$=$2;}
        |       '-' expr %prec UMINUS   {$$=-$2;}
        |       NUMBER		{$$=$1;}								
        ;
%%

// programs section

int yylex()
{
    int t;
    while(1){
        t=getchar();
        if(t==' '||t=='\t'||t=='\n'||t=='\r'){
         ;//do noting
        }else if(isdigit(t)){
            //TODO:解析多位数字返回数字类型 
            /*yacc内部定义的变量yylval用于传递属性值*/
            yylval = 0;
            while(isdigit(t)) {
               yylval = yylval * 10 + t -'0';
               t = getchar();
            }
            ungetc(t , stdin);
            return NUMBER;
        }else if(t=='+'){
            return '+';
        }else if(t=='-'){
            return '-';
        }//TODO:识别其他符号
        else if(t=='*'){
            return '*';
        }else if(t=='/'){
            return '/';
        }else if(t=='('){
            return '(';
        }else if(t==')'){
            return ')';
        }else{
            return t;
        }
    }
}

int main(void)
{
    yyin=stdin;
    do{
        yyparse();
    }while(!feof(yyin));
    return 0;
}
void yyerror(const char* s){
    fprintf(stderr,"Parse error: %s\n",s);
    exit(1);
}
